package com.yidian.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yidian.dao.SeckillGoodsMapper;
import com.yidian.dao.SeckillOrderMapper;
import com.yidian.pojo.seckill.SeckillGoods;
import com.yidian.pojo.seckill.SeckillOrder;
import com.yidian.pojo.seckill.SeckillStatus;
import com.yidian.server.seckill.SeckillOrderServcie;
import com.yidian.task.MultiThreadingCreateOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Date;

/**
 * @author whb
 * @create 2021-10-25 09:50
 * @desciption 秒杀订单Service接口实现类
 */
@Service
public class SeckillOrderServiceImpl implements SeckillOrderServcie {
    @Autowired
    private MultiThreadingCreateOrder multiThreadingCreateOrder;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillOrderMapper seckillOrderMapper;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    /**
     * 秒杀下单
     *
     * @param id       商品id
     * @param time     商品秒杀时间区间
     * @param username 用户名
     * @return
     */
    @Override
    public Boolean addOrder(Long id, String time, String username) {
        //判断是否有库存
        Long size = redisTemplate.boundListOps("SeckillGoodsCountList_"+id).size();
        if (size==null||size<=0){
            throw new RuntimeException("101");//101：商品已经售罄
        }

        Long userQueueCount = redisTemplate.boundHashOps("UserQueueCount").increment(username, 1);//设置队列排队值，判断是否正在排队，采用redis缓存increment自增方法
        //当排队值大于1，秒杀已经过了，正在排队中，不能再重复提交
        if (userQueueCount>1){
            throw new RuntimeException("100");
        }

        SeckillStatus seckillStatus=new SeckillStatus(username, new Date(), 1, id, time);//创建秒杀信息对象
        redisTemplate.boundListOps("SeckillOrderQueue").leftPush(seckillStatus);//将秒杀信息存入redis缓存，这里采用List方式存储，List本身就是一个队列
        redisTemplate.boundHashOps("UserQueueStatus").put(username, seckillStatus);//将秒杀信息存入redis缓存，用于在秒杀过程中查询和修改状态
        multiThreadingCreateOrder.createOrder();
        System.out.println("Spring多线程正在进行异步处理..");
        return true;
    }

    /**
     * 查询秒杀状态信息
     * @param username 用户名
     * @return
     */
    @Override
    public SeckillStatus querySeckillStatus(String username) {
        return (SeckillStatus) redisTemplate.boundHashOps("UserQueueStatus").get(username);
    }

    /**
     * 更新秒杀订单状态
     * @param out_trade_no 订单号
     * @param username 用户名
     * @param transaction_id 交易流水号
     */
    @Override
    public void updateOrderStatus(String out_trade_no, String username, String transaction_id) {
        SeckillOrder seckillOrder = (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder").get(username);//从redis缓存中取出订单数据
        if (seckillOrder!=null){
            seckillOrder.setStatus("1");//支付状态，0：未支付，1：已支付
            seckillOrder.setCreateTime(new Date());//订单创建时间
            seckillOrder.setTransactionId(transaction_id);//交易流水号
            seckillOrderMapper.insertSelective(seckillOrder);//将订单数据同步到MySql数据库中

            Long seckillId = seckillOrder.getSeckillId();//获取订单中商品id
            Long seckillGoodsCount = redisTemplate.boundHashOps("SeckillGoodsCount").increment(seckillId, 0);//商品剩余库存
            SeckillGoods seckillGoods=new SeckillGoods();
            seckillGoods.setId(seckillId);//设置秒杀商品id
            seckillGoods.setStockCount(seckillGoodsCount.intValue());//设置剩余库存
            seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);//将剩余库存量同步到MySql数据库中


            redisTemplate.boundHashOps("SeckillOrder").delete(username);//清除redis缓存中的订单数据
            redisTemplate.boundHashOps("UserQueueCount").delete(username);//清除redis缓存中的排队队列数据
            redisTemplate.boundHashOps("UserQueueStatus").delete(username);//清除redis缓存中秒杀状态数据
        }
    }

    /**
     * 根据用户名查询秒杀订单数据
     * @param username 用户名
     * @return
     */
    @Override
    public SeckillOrder querySeckillOrder(String username) {
        return (SeckillOrder) redisTemplate.boundHashOps("SeckillOrder").get(username);
    }
}
